﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace SharePoint.ImportExport.Importer.Helpers
{
    public class InfoPathFormHelper
    {

        /// <summary>
        /// This method extracts the data from the specified package
        /// </summary>
        /// <param name="package">Full Paths to package file</param>
        /// <param name="directory">Directory that the files will be extracted to</param>
        /// <returns></returns>
        private bool Extract(string package, string directory)
        {
            bool returnValue = true;
            FileInfo fi = new FileInfo(package);

            Directory.CreateDirectory(directory);

            Process p = new Process();
            ProcessStartInfo pInfo = new ProcessStartInfo("extrac32.exe");
            pInfo.WorkingDirectory = fi.DirectoryName;
            pInfo.Arguments = "/E /L \"" + directory + "\" \"" + package + "\"";
            pInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo = pInfo;
            p.Start();
            p.WaitForExit();
            int code = p.ExitCode;

            return returnValue;
        }


        /// <summary>
        /// This method compresses all files specified in the struct.xml file
        /// </summary>
        /// <param name="structFile">Path and filename of the struct.xml file</param>
        /// <param name="packageFolder">Folder that will contain the packaged data</param>
        /// <returns></returns>
        private bool Compress(string path, string formName)
        {
            bool returnValue = true;
            using (StreamWriter sw = new StreamWriter(path + "\\data.ddf", false))
            {
                sw.WriteLine(";*** SharePoint ImportExportData");
                sw.WriteLine(";");
                sw.WriteLine(".OPTION EXPLICIT     ; Generate errors");
                sw.WriteLine(".Set CabinetNameTemplate={0}", formName);
                sw.WriteLine(".set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory");
                sw.WriteLine(".Set CompressionType=MSZIP;** All files are compressed in cabinet files");
                sw.WriteLine(".Set UniqueFiles=\"OFF\"");
                sw.WriteLine(".Set Cabinet=on");
                sw.WriteLine(".Set DiskDirectory1=XSN");
                sw.WriteLine(".Set MaxDiskSize=CDROM	; 3.5\" disks");
                sw.WriteLine("manifest.xsf");
                sw.WriteLine("sampledata.xml");
                sw.WriteLine("schema.xsd");
                sw.WriteLine("schema1.xsd");
                sw.WriteLine("schema2.xsd");
                sw.WriteLine("schema3.xsd");
                sw.WriteLine("schema4.xsd");
                sw.WriteLine("template.xml");
                sw.WriteLine("upgrade.xsl");
                sw.WriteLine("view1.xsl");
                sw.Flush();
            }

            Process p = new Process();
            ProcessStartInfo pInfo = new ProcessStartInfo("makecab.exe");
            pInfo.WorkingDirectory = path;
            pInfo.Arguments = "/f " + path + "\\data.ddf";
            pInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo = pInfo;

            p.Start();
            p.WaitForExit();
            int code = p.ExitCode;

            return returnValue;
        }

        public bool ProcessXsn(string path, string formName, string url, string listID, string contentTypeID)
        {
            bool returnValue = false;
            Guid g = Guid.NewGuid();
            Directory.SetCurrentDirectory(path);
            if (Extract(path + "\\" + formName, g.ToString()))
            {
                string[] data = System.IO.File.ReadAllLines(path + "\\"+g.ToString()+"\\manifest.xsf");
                int max = data.Length;
                for (int i = 0; i < max; i++)
                {
                    string s = data[i];
                    int index = s.IndexOf("baseUrl relativeUrlBase") + 25;
                    if (index > 25)
                    {

                        string s2 = s.Substring(index);
                        index = s2.IndexOf("/Lists");
                        s2 = s2.Substring(0, index);
                        data[i] = s.Replace(s2, url);
                    }
                    index = s.IndexOf("sharePointListID=") + 18;
                    if (index > 18)
                    {

                        string s2 = s.Substring(index);
                        index = s2.IndexOf("}");
                        s2 = s2.Substring(0, index + 1);
                        data[i] = s.Replace(s2, listID);
                        s = data[i];
                    }
                    index = s.IndexOf("contentTypeID=") + 15;
                    if (index > 15)
                    {

                        string s2 = s.Substring(index);
                        index = s2.IndexOf("\"");
                        s2 = s2.Substring(0, index);
                        data[i] = s.Replace(s2, contentTypeID);
                    }

                }

                System.IO.File.WriteAllLines(path + "\\" + g.ToString() + "\\manifest.xsf", data);
                if (Compress(path + "\\" + g.ToString(), formName))
                {
                    File.Delete(path + "\\" + g.ToString()+"\\manifest.xsf");
                    File.Delete(path + "\\" + g.ToString() + "\\sampledata.xml");
                    File.Delete(path + "\\" + g.ToString() + "\\schema.xsd");
                    File.Delete(path + "\\" + g.ToString() + "\\schema1.xsd");
                    File.Delete(path + "\\" + g.ToString() + "\\schema2.xsd");
                    File.Delete(path + "\\" + g.ToString() + "\\schema3.xsd");
                    File.Delete(path + "\\" + g.ToString() + "\\schema4.xsd");
                    File.Delete(path + "\\" + g.ToString() + "\\template.xml");
                    File.Delete(path + "\\" + g.ToString() + "\\upgrade.xsl");
                    File.Delete(path + "\\" + g.ToString() + "\\view1.xsl");
                    File.Delete(path + "\\" + g.ToString() + "\\setup.inf");
                    File.Delete(path + "\\" + g.ToString() + "\\setup.rpt");
                    File.Delete(path + "\\" + g.ToString() + "\\data.ddf");
                    

                    byte[] xsndata = System.IO.File.ReadAllBytes(path + "\\" + g.ToString()+"\\XSN\\" + formName);
                    if (xsndata.Length > 0)
                    {
                        File.Delete(path + "\\" + g.ToString() + "\\XSN\\" + formName);
                        Directory.Delete(path + "\\" + g.ToString(), true);
                        string fdata = Convert.ToBase64String(xsndata);
                        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url + "/_vti_bin/formsservices.asmx");
                        req.Method = "POST";
                        req.UseDefaultCredentials = true;
                        req.ContentType = "text/xml; charset=utf-8";
                        req.Headers.Add("SOAPAction", "http://schemas.microsoft.com/office/infopath/2007/formsServices/SetFormsForListItem");
                        string SOAPmessage = "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><SetFormsForListItem xmlns=\"http://schemas.microsoft.com/office/infopath/2007/formsServices\"><lcid>1033</lcid><base64FormTemplate>" + fdata + "</base64FormTemplate><applicationId>InfoPath 14</applicationId><listGuid>" + listID + "</listGuid><contentTypeId>" + contentTypeID + "</contentTypeId></SetFormsForListItem></soap:Body></soap:Envelope>";
                        byte[] bts = System.Text.Encoding.UTF8.GetBytes(SOAPmessage);
                        req.ContentLength = bts.Length;
                        req.Timeout = 20000;
                        Stream dataStream = req.GetRequestStream();
                        dataStream.Write(bts, 0, bts.Length);
                        dataStream.Close();
                        HttpWebResponse response = (HttpWebResponse)req.GetResponse();
                        
                        Stream inputStream = response.GetResponseStream();

                        returnValue = (response.StatusCode == HttpStatusCode.OK);
                    }
                }

            }
            return returnValue;
        }
    }
}
